﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections;

namespace Maestro_Proveedores.clases.almacen
{
    class MediaMovil : ModeloAbstracto
    {
        ArrayList resultadosN;
        
        //-------------------------CONSTRUCTOR DE CLASE

        public MediaMovil()
        {
            this.nombreModelo = "Media Movil";
            this.resultadosN = new System.Collections.ArrayList();
            resNideal = new Resultado();
        }


        //------------------------ INICIO METODOS SOBREESCRITOS

        public override Resultado obtenerResultado()
        {
            return this.resNideal;
        }

        public override void pronosticoSemanaN()
        {
            // se realiza una copia de la lista original, para cada calculo de N
            ArrayList registrosClon = new ArrayList();
            registrosClon = copiarArrayList(registros);
            semanaPronostico = registros.Count;
            //registrosClon.Add(new Registro(this.semanaPronostico,0));
            //ArrayList listpronostico = calcularPronostico(this.resNideal.N);
            resNideal.pronosticoN1 = sumatoriaParcial(semanaPronostico + 1, this.resNideal.N) / this.resNideal.N;
        }
        
        
        public override void calcularModelo(ArrayList reg)
        {
            this.registros = reg;
            int limite = 15;

            if (limite > registros.Count)
            {
                limite = registros.Count;
            }

            for (int i = 1; i <= limite; i++)
            {
                ArrayList registrosTemp = calcularPronostico(i);
                Resultado res = calcularResultados(registrosTemp);
                res.N = i;
                resultadosN.Add(res);
            }

            this.buscarNideal();

            resNideal.RegistrosFinal = calcularPronostico(resNideal.N);
            // se calcula el pronostico para la siguiente semana (N+1) se al macena en el resNIDEal
            pronosticoSemanaN();
            //this.mostrarArreglo("Media Movil-N-" + resNideal.N, registrosFinal);

        }

        //------------------------ FIN METODOS SOBREESCRITOS

        private ArrayList calcularPronostico(double n)
        {

            // se realiza una copia de la lista original, para cada calculo de N
            ArrayList registrosClon = new ArrayList();
            registrosClon = copiarArrayList(registros);

            int totalSemanas = registrosClon.Count;

            if (n <= totalSemanas)
            {
                int index = 1;
                foreach (Registro reg in registrosClon)
                {
                    if (index > n)
                    {
                        //se calcula el pronostico
                        reg.Pronostico = sumatoriaParcial(reg.Semana, n) / n;

                        if (index > n)
                        {
                            //se calcula el et
                            reg.Et = reg.Demanda - reg.Pronostico;
                            //se calcula el etabsoluto
                            reg.Etabsoluto = Math.Abs(reg.Et);
                            //se calcula el etcuadrado
                            reg.Etcuadrado = Math.Pow(reg.Et, 2);
                            //se calcula el APE
                            reg.Ape = 100 * (Math.Abs(reg.Et / reg.Demanda));
                            //se calcula el APE1
                            reg.Ape1 = 100 * (Math.Abs(reg.Et / reg.Pronostico));
                        }

                    }
                    index++;
                }

            }

            return registrosClon;
        }

        public void mostrarArreglo(String nombre, ArrayList registro){
            //Gestion_Inventario_Proveedores.clases.herramientas.FileManager file = new Gestion_Inventario_Proveedores.clases.herramientas.FileManager();
            //file.generarArchivo(registro, nombre);
        }


        //sumatoria parcial que apoya el pronostico
        private double sumatoriaParcial(double semana, double n)
        {
            int sumatoria = 0;
            double limiteInferior = (semana - n);

            foreach (Registro reg in registros)
            {
                if (reg.Semana >= limiteInferior & reg.Semana < semana)
                {
                    sumatoria += reg.Demanda;
                }
            }

            return sumatoria;
        }

        // metodo que calcula el MAD, ECM, MAPE y MAPE1 para cada lista
        // recibe un arreglo de registros

        private Resultado calcularResultados(ArrayList registros)
        {
            Resultado resultado = new Resultado();

            double sumatoriaMAD = 0;
            double sumatoriaECM = 0;
            double sumatoriaMAPE = 0;
            double sumatoriaMAPE1 = 0;
            double count = 0;
             
            foreach (Registro reg in registros)
            {
                if (reg.Pronostico != 0)
                {
                    sumatoriaMAD += reg.Etabsoluto;
                    sumatoriaECM += reg.Etcuadrado;
                    sumatoriaMAPE += reg.Ape;
                    sumatoriaMAPE1 += reg.Ape1;
                    count++;
                }
            }

            resultado.ECM = sumatoriaECM / count;
            resultado.MAD = sumatoriaMAD / count;
            resultado.MAPE = sumatoriaMAPE / count;
            resultado.MAPE1 = sumatoriaMAPE1 / count;

            resultado.RegistrosFinal = registros;

            return resultado;
        }

        public string mostrarArreglo()
        {
            string msj = "";

            foreach (Resultado reg in resultadosN)
            {
                msj += "N: " + reg.N +
                    //"\nMAD: " + reg.MAD + 
                    "\nECM: " + reg.ECM + "\n -----------------------------";
                //"\nMAPE: " + reg.MAPE +
                //"\nMAPE1: " + reg.MAPE1 + "\n -----------------------------";

            }
            msj += "El n ideal es:" + this.resNideal.N;
            return msj;
        }

        public void buscarNideal()
        {
            double nideal = 0;
            foreach (Resultado res in resultadosN)
            {
                nideal = res.ECM;
                this.resNideal = res;
            }

            foreach (Resultado res in resultadosN)
            {
                if (res.ECM < nideal)
                {
                    nideal = res.ECM;
                    this.resNideal = res;
                }
            }

        }

       
    }

}
